import React, { useEffect, useMemo, useRef } from "react";
import { Tldraw } from "tldraw";
import * as Y from "yjs";
import "tldraw/tldraw.css";

/**
 * WhiteboardBlockView（方案一：JSON 快照同步）
 * - 使用 @tldraw/tldraw 2.x
 * - 将 tldraw 的快照（editor.store.getSnapshot()）作为块 props.data.tldrawJson 存储
 * - 文档层（BlockNote + Yjs）负责 CRDT 与最终存储
 */
type WhiteboardData = {
  version: number;
  tldrawJson: any;
  preview?: string | null;
  assets?: Array<{ id: string; type: string; url: string; w?: number; h?: number }>;
};

export function WhiteboardBlockView({ block, editor }: { block: any; editor: any }) {
  // 保存 tldraw 编辑器实例，便于读写快照与订阅事件
  const tlEditorRef = useRef<any | null>(null);
  // 本地写入标记：避免“本地写 -> 文档层 -> 回流刷新”造成循环
  const isLocalRef = useRef(false);
  // 统一日志前缀（包含 blockId / user）
  const userName = editor?.options?.collaboration?.user?.name || "unknown";
  const log = (...args: any[]) => {
    try {
      // console.log("[Whiteboard]", { blockId: block?.id, user: userName }, ...args);
    } catch {}
  };
  // 统一收集需要解除的监听
  const disposersRef = useRef<Array<() => void>>([]);

  // 协同容器：为当前块建立 Y.Text，用于存储整树 JSON 快照
  // 命名规范：whiteboard-json:<blockId>
  const yText = useMemo(() => {
    const fragment = editor?.options?.collaboration?.fragment as Y.XmlFragment | undefined;
    if (!fragment) return null;
    const ydoc = (fragment as any).doc as Y.Doc | undefined;
    if (!ydoc) return null;
    const key = `whiteboard-json:${block.id}`;
    const text = ydoc.getText(key);
    log("yText init", { key, length: text.length, clientID: (ydoc as any)?.clientID });
    return text;
  }, [block.id, editor]);

  // 取初始快照：优先从 Y.Text 读取；否则回落到块 props.data.tldrawJson
  const initialSnapshot = useMemo(() => {
    // A) 协同：从 Y.Text 解析
    if (yText && yText.length > 0) {
      try {
        const raw = yText.toString();
        const parsed = JSON.parse(raw);
        if (parsed && typeof parsed === "object" && (parsed as any).store) {
          log("initial snapshot from Y.Text", {
            length: raw.length,
            hasStore: !!(parsed as any).store
          });
          return parsed;
        } else {
          log("yText content not a tldraw snapshot (no store), ignore", { preview: raw.slice(0, 120) });
        }
      } catch (e) {
        log("yText JSON parse error", e);
      }
    } else {
      log("yText empty or null");
    }
    // B) 回落：从块 props
    const data: WhiteboardData | undefined = block?.props?.data;
    const snap = data?.tldrawJson ?? null;
    if (snap && typeof snap === "object") {
      if ((snap as any).store) {
        log("initial snapshot from props.data.tldrawJson", { hasStore: true });
        return snap;
      } else {
        log("props.tldrawJson not a snapshot (no store)");
      }
    } else {
      log("props.tldrawJson empty or null");
    }
    return null;
  }, [block.id, yText]);

  // 将编辑器当前状态节流写回文档（每 200ms 最多一次），减少网络/CPU 压力
  const writeTimer = useRef<any>(null);

  // 本地编辑的时候 写入 编辑器的 props
  const scheduleWrite = () => {
    if (writeTimer.current) return;
    writeTimer.current = setTimeout(() => {
      writeTimer.current = null;
      if (!tlEditorRef.current || isLocalRef.current) return;
      // 获取 tldraw 当前快照
      const snapshot = tlEditorRef.current.store.getSnapshot();
      // 合并写回：version 自增（可用于并发覆盖校验/日志）
      const prev: WhiteboardData = block?.props?.data || { version: 1, tldrawJson: {} };
      // 将 新版本的 数据 合并写入到 编辑器的 props中
      log("props.updateBlock", {
        nextVersion: (prev.version || 0) + 1,
        schemaVersion: (snapshot as any)?.schemaVersion,
        hasStore: !!(snapshot as any)?.store
      });
      editor.updateBlock(block, {
        props: { data: { ...prev, version: (prev.version || 0) + 1, tldrawJson: snapshot } }
      });
      // 同步到 Y.Text：保证协同与刷新恢复
      try {
        if (yText) {
          const jsonStr = JSON.stringify(snapshot);
          log("yText.write", { length: jsonStr.length });
          const ydoc = (yText as any).doc as Y.Doc | undefined;
          if (ydoc) {
            Y.transact(ydoc, () => {
              yText.delete(0, yText.length);
              yText.insert(0, jsonStr);
            });
          } else {
            yText.delete(0, yText.length);
            yText.insert(0, jsonStr);
          }
        }
      } catch {}
    }, 200);
  };

  // 当块 props.data.tldrawJson 来自远端更新（文档层 CRDT）时，回放到 tldraw
  useEffect(() => {
    if (!tlEditorRef.current || !initialSnapshot) return;
    try {
      isLocalRef.current = true;
      log("loadSnapshot(initial)", { schemaVersion: (initialSnapshot as any)?.schemaVersion });
      tlEditorRef.current.store.loadSnapshot(initialSnapshot);
    } finally {
      isLocalRef.current = false;
    }
  }, [initialSnapshot]);

  // 订阅 Y.Text：远端协同/刷新 -> 更新 tldraw 视图
  // 移至 onMount 内进行绑定，确保 editor 实例可用

  // 订阅编辑器变更：改为 onMount 内绑定

  return (
    <div style={{ width: block.props.width, height: block.props.height }}>
      <Tldraw
        onMount={(ed: any) => {
          // 1) 保存编辑器实例引用
          tlEditorRef.current = ed;
          log("tldraw.onMount", { hasInitial: !!initialSnapshot });
          // 2) 初次挂载：如果已有快照则加载（通常来自协同/历史）
          if (initialSnapshot) {
            try {
              isLocalRef.current = true;
              log("onMount -> loadSnapshot", { schemaVersion: (initialSnapshot as any)?.schemaVersion });
              ed.store.loadSnapshot(initialSnapshot);
            } finally {
              isLocalRef.current = false;
            }
          }
          // 3) 绑定编辑器变更 -> 写回（props + Y.Text）
          const handleChange = () => scheduleWrite();
          ed.on?.("change", handleChange);
          log("editor.on(change) attach (onMount)");
          disposersRef.current.push(() => {
            ed.off?.("change", handleChange);
            log("editor.off(change) detach (cleanup)");
          });
          // 4) 绑定 Y.Text 监听 -> 远端/刷新回放
          if (yText) {
            const onYChange = () => {
              if (isLocalRef.current) return;
              try {
                const txt = yText.toString();
                if (!txt) return;
                const parsed = JSON.parse(txt);
                if (parsed && typeof parsed === "object" && (parsed as any).store) {
                  log("Y.Text -> loadSnapshot", { length: txt.length, schemaVersion: (parsed as any).schemaVersion });
                  isLocalRef.current = true;
                  tlEditorRef.current?.store.loadSnapshot(parsed);
                }
              } catch {
              } finally {
                isLocalRef.current = false;
              }
            };
            yText.observe(onYChange);
            log("observe Y.Text (onMount)");
            disposersRef.current.push(() => {
              yText.unobserve(onYChange);
              log("unobserve Y.Text (cleanup)");
            });

            // 5) 兜底：若初始没有加载到快照，但此时 Y.Text 已有内容，则立即尝试一次加载
            if (!initialSnapshot && yText.length > 0) {
              try {
                const txt = yText.toString();
                const parsed = JSON.parse(txt);
                if (parsed && typeof parsed === "object" && (parsed as any).store) {
                  log("fallback load from Y.Text (onMount)", { length: txt.length });
                  isLocalRef.current = true;
                  tlEditorRef.current?.store.loadSnapshot(parsed);
                }
              } catch {
              } finally {
                isLocalRef.current = false;
              }
            }
          }
        }}
      />
    </div>
  );
}

export default WhiteboardBlockView;
